#pragma once

class Database
{
public:
	static DWORD VERSION;

	static void Initialize();
	static void Finalize();

	static Database& getSingleton();

	template <class DATA_TYPE>
	class Table
	{
	public:
		bool Load(const char* filename);
		void Save(const char* filename);

		struct DataFinder
		{
			 DataFinder(unsigned dataID) 
				: mFindingDataID(dataID)
			{ 
			}
			bool operator ()(const DATA_TYPE& data) const
			{
				return mFindingDataID == data.mID;
			}

			unsigned mFindingDataID;
		};

		const DATA_TYPE& GetDataWithIDConst(DWORD ID) const
		{
			static DATA_TYPE temp;
			DATAS::iterator it = msData.begin(), itend = msData.end();
			for (;it!=itEnd;it++)
			{
				if (it->mID == ID)
					return *data;
			}

			return temp;
		}
		DATA_TYPE& GetDataWithID(DWORD ID)
		{
			static DATA_TYPE temp;
			DATAS::iterator it = msData.begin(), itend = msData.end();
			for (;it!=itend;it++)
			{
				if (it->mID == ID)
					return (*it);
			}
			return temp;
		}
		bool RemoveDataWithID(DWORD ID)
		{
			bool removed = std::find_if(msData.begin(), msData.end(), 
				DataFinder(ID)) != msData.end();
			msData.erase( std::remove_if(msData.begin(), msData.end(), DataFinder(ID)) );

			return removed;
		}

		unsigned AcquireID()
		{
			DWORD newID = 0;
			DATAS::iterator it = msData.begin(), itend = msData.end();
			for (;it!=itEnd;it++)
			{
				if (newID < it->mID)
				{
					newID = it->mID;
				}
			}
			return newID+1;
		}
	
		DATA_TYPE& New()
		{
			unsigned newID = AcquireID();
			DATA_TYPE newData;
			newData.mID = newID;
			msData.push_back(newData);
			return msData.back();
		}

		typedef std::vector<DATA_TYPE> DATAS;
		DATAS msData;
		std::string mFilename;
	};

	enum
	{
		INVALID_ID = 0,
	};

	struct ErrorMessage
	{
		ErrorMessage()
		{
			mID = INVALID_ID;
		}

		DWORD mID;
		std::string mMsg;
	};	

	//---------------------------------------------------------------------------
	typedef Table<ErrorMessage> ERROR_MESSAGE_TABLE;
	typedef ERROR_MESSAGE_TABLE::DATAS ERROR_MESSAGE_DATAS;

	//---------------------------------------------------------------------------
	bool SaveAll();
	void SaveErrorMessagesTable(const char* filename);
	bool LoadErrorMessagesTable(const char* filename);
	
	//---------------------------------------------------------------------------
	ERROR_MESSAGE_TABLE& GetErrorMessageTable();

	// Database specific


private:
	static const std::string ERROR_MESSAGE_TABLE_FILE_NAME;

	static ERROR_MESSAGE_TABLE *msErrorMsgTable;

	private:
		Database(){}
		Database(const Database& rhs);
		Database& operator=(const Database& rhs);
};